home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
422_02
/
dosutil
/
retab.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-20
|
5KB
|
187 lines
/*
* Retabulates files to different tab stops
*
* Options:
* -f = Inhibit filling with spaces
* -s = Convert spaces to tabs where possible
* i=n,... = Specify input tab stops
* o=n,... = Specify output tab stops
*
* Notes:
* RETAB processes multiple files, and allows the tab settings to be defined
* for each file. The '-f -s i= and o=' parameters must be specified BEFORE
* the file name where they are to have effect.
*
* If more tabs are present in the input or output file than were specified
* (using I= and O=), RETAB assumes that the tabs continue at the spacing of
* the last two stops. Therefore, if the tabs are at regular intervals, only
* the first tab stop need be given.
*
* Both input and output tabs default to 8 space intervals.
*
* If 'O=0' is specified, RETAB will convert all tabs in the input file to
* the appriopriate number of spaces.
*
* Examples:
* retab i=4 tab4.fil >tab8.fil
* retab o=4 tab8.fil >tab4.fil
* retab i=4 o=2 tab4.file i=8 tab8.fil >tab2.fil
* retab o=0 tab8.file >space.fil
*
* Copyright 1988-1994 Dave Dunfied
* All rights reserved.
*
* Permission granted for personal (non-commercial) use only.
*
* Compile command: cc retab -fop
*/
#include <stdio.h>
#define TAB_STOPS 25 /* maximum number of tab stops supported */
unsigned itabs[TAB_STOPS], otabs[TAB_STOPS];
char fill = -1, space = 0, *ptr;
main(argc, argv)
int argc;
char *argv[];
{
unsigned i, j, k, l;
FILE *fp;
char flag, flag1;
flag = -1;
flag1 = 0;
/* Install default tabs at 8 space intervals */
for(i=j=0; i < TAB_STOPS; ++i)
itabs[i] = otabs[i] = (j += 8);
/* parse the options and parameters */
for(i=1; i < argc; ++i) {
ptr = argv[i];
switch((tolower(*ptr++) << 8) | tolower(*ptr++)) {
case '-f': /* disable fill */
fill = 0;
goto parm;
case '-s': /* enable space processing */
space = -1;
goto parm;
case '-i': /* specify input tabs */
j = 0;
do
itabs[j++] = k = l = get_dec();
while(*ptr++ == ',');
if(j > 1)
k -= itabs[j-2];
while(j < (sizeof(itabs)/2))
itabs[j++] = l += k;
goto parm;
case 'o=': /* specify output tabs */
j = 0;
do
otabs[j++] = k = l = get_dec();
while(*ptr++ == ',');
if(j > 1)
k -= otabs[j-2];
while(j < (sizeof(otabs)/2))
otabs[j++] = l += k;
parm:
flag1 = -1;
break;
default:
flag = flag1 = 0;
if(fp = fopen(argv[i], "r")) {
do_convert(fp);
fclose(fp); }
else {
fputs("RETAB: Cannot open: '", stderr);
fputs(argv[i], stderr);
fputs("'\n", stderr); } } }
if(flag1)
fputs("RETAB: Trailing options have no effect!!!\n", stderr);
if(flag)
fputs("\nUse: retab [-f -s i=n,n,n... o=n,n,n] <file*> >output_file\n\nCopyright 1988-1994 Dave Dunfield\nAll rights reserved.\n", stderr);
}
/* get a decimal number from the input line */
get_dec()
{
unsigned value;
value = 0;
if(isdigit(*ptr)) { /* decimal number */
while(isdigit(*ptr))
value = (value * 10) + *ptr++ - '0'; }
else {
fputs("RETAB: Invalid number\n", stderr);
exit(-1); }
return(value);
}
/* do the tab conversion */
do_convert(fp)
FILE *fp;
{
unsigned ip, op, i, scount;
char chr;
ip = op = scount = 0;
while((chr = getc(fp)) != -1) { /* read entire file */
if(chr == 0x09) { /* found a tab */
ip += scount; /* offset for any spaces */
for(i=0; ip >= itabs[i]; ++i); /* next input tab position */
ip = itabs[i];
scount = 0; }
else if((chr == ' ') && space) /* convert spaces */
++scount;
else { /* std character */
/*
* if more than 1 space is encountered, or a single space
* is adjacent to a one or more tabs, convert it to tabs.
*/
if((op < ip) || (scount > 1)) {
ip += scount;
scount = 0; }
/*
* if the output pointer lags behind the input pointer
* we have received tabs or multiple spaces. Generate
* tabs in the output file to restore the position.
*/
if(op < ip) { /* we have whitespace to fill in */
for(i=0; op >= otabs[i]; ++i); /* next output tab position */
while(otabs[i] <= ip) {
putc(0x09, stdout);
op = otabs[i++]; }
/*
* Input pointer is not on an output tab stop, fill with
* spaces as nessary, to restore the correct position.
*/
if(fill) while(op < ip) {
putc(' ', stdout);
++op; }
else
op = ip; }
++ip;
/*
* Single space received, copy to output file
*/
if(scount) {
putc(' ', stdout);
++op;
++ip;
scount = 0; }
/*
* Copy character into output file
*/
putc(chr, stdout);
++op;
if(chr == '\n')
ip = op = 0; } }
}